/*
 *    Copyright (c) 2018-2025, cloud All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: cloud
 */
package com.fuyao.cloud.asset.borrow.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuyao.cloud.admin.api.feign.RemoteUserService;
import com.fuyao.cloud.admin.api.vo.UserVO;
import com.fuyao.cloud.asset.borrowlist.service.BorrowListService;
import com.fuyao.cloud.asset.card.service.AssetAssetcardService;
import com.fuyao.cloud.asset.dto.borrow.BorrowCreateDTO;
import com.fuyao.cloud.asset.dto.borrow.BorrowEditDTO;
import com.fuyao.cloud.asset.dto.borrow.BorrowExcelDTO;
import com.fuyao.cloud.asset.dto.borrow.BorrowSearchDTO;
import com.fuyao.cloud.asset.entity.AssetCard;
import com.fuyao.cloud.asset.entity.borrow.Borrow;
import com.fuyao.cloud.asset.borrow.mapper.BorrowMapper;
import com.fuyao.cloud.asset.borrow.service.BorrowService;
import com.fuyao.cloud.asset.entity.borrow.BorrowList;
import com.fuyao.cloud.asset.entity.receive.ReceiveList;
import com.fuyao.cloud.asset.entity.warehous.Warehous;
import com.fuyao.cloud.asset.enums.AssetStatusEnum;
import com.fuyao.cloud.asset.enums.BorrowStatusEnum;
import com.fuyao.cloud.asset.enums.CardStatusEnum;
import com.fuyao.cloud.common.core.constant.CommonConstants;
import com.fuyao.cloud.common.core.model.BaseEntity;
import com.fuyao.cloud.common.core.util.R;
import com.fuyao.cloud.common.data.datascope.DataScope;
import com.fuyao.cloud.common.data.resolver.NumberResolver;
import com.fuyao.cloud.common.data.resolver.ParamResolver;
import com.fuyao.cloud.common.security.service.CloudUser;
import com.fuyao.cloud.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 借用&归还表
 *
 * @author ly
 * @date 2022-01-06 10:37:40
 */
@Service
@AllArgsConstructor
public class BorrowServiceImpl extends ServiceImpl<BorrowMapper, Borrow> implements BorrowService {

	private final BorrowListService borrowListService;
	private final RemoteUserService userService;
	private final AssetAssetcardService assetCardService;

	@Transactional
	@Override
	public boolean save(Borrow entity) {
		saveOrUpdateBefore(entity);
		boolean hasSave = super.save(entity);
		if (hasSave) {
			borrowListService.saveOrUpdateBorrowList(entity);
		}
		return hasSave;
	}

	@Transactional
	@Override
	public boolean updateById(Borrow entity) {
		saveOrUpdateBefore(entity);
		boolean hasUpdate = super.updateById(entity);
		if (hasUpdate) {
			borrowListService.saveOrUpdateBorrowList(entity);
		}
		return hasUpdate;
	}

	@Override
	public BorrowCreateDTO create() {
		CloudUser user = SecurityUtils.getUser();
		String caseKey = ParamResolver.getStr("BORROW_CASE_VALUE", "ABR");
		Map<String, String> numberMap = NumberResolver.getNumberMap(Borrow.BORROW_CASE_TYPE, DateUtil.format(new Date(), DatePattern.SIMPLE_MONTH_PATTERN), 5L).getData();
		String caseid = caseKey + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN + numberMap.get("code"));

		return BorrowCreateDTO.builder()
				.unid(UUID.randomUUID().toString())
				.createId(user.getId())
				.caseid(caseid)
				.createBy(user.getName())
				.type(Borrow.BORROW)
				.deptId(user.getDeptId())
				.status(BorrowStatusEnum.EFFECT.getCode())
				.createTime(LocalDateTime.now())
				.deptFullname(user.getFullName())
				.borrowTime(LocalDateTime.now())
				.dictOption(getDictOption())
				.build();
	}

	@Override
	public BorrowEditDTO edit(Long id) {
		Borrow borrow = this.getById(id);
		Assert.isTrue(ObjectUtils.isNotEmpty(borrow), String.format("%s不合法", id));
		BorrowEditDTO editDTO = BorrowEditDTO.builder().build();
		BeanUtil.copyProperties(borrow, editDTO);
		List<BorrowList> borrowList = this.borrowListService.getBaseMapper().selectList(Wrappers.<BorrowList>query().lambda().eq(BorrowList::getParentId, borrow.getId()));
		editDTO.setBorrowList(borrowList);
		editDTO.setDictOption(getDictOption());
		return editDTO;
	}

	@Override
	public boolean updateRemand(List<Long> ids) {
		LambdaQueryWrapper<Borrow> queryWrapper = Wrappers.<Borrow>query().lambda().in(BaseEntity::getId, ids);
		CloudUser user = SecurityUtils.getUser();
		List<Borrow> borrows = this.list(queryWrapper);
		if (CollUtil.isNotEmpty(borrows)) {
			borrows.forEach(borrow -> {
				borrow.setType(Borrow.REMAND);
				borrow.setRemandId(user.getId());
				borrow.setRealRemandTime(LocalDateTime.now());
				borrow.setRemandName(user.getName());
				borrow.setRemandOuname(user.getOuName());
				borrow.setRemandOuid(user.getDeptId());
				borrow.setRemandOufullname(user.getFullName());
			});
			List<Long> assetCardIds = Lists.newArrayList();
			List<Long> borrowIds = borrows.stream().map(BaseEntity::getId).collect(Collectors.toList());
			List<BorrowList> borrowList = this.borrowListService.listParentId(borrowIds);
			if (CollUtil.isNotEmpty(borrowList)) {
				assetCardIds.addAll(borrowList.stream().map(BorrowList::getAssetCardId).collect(Collectors.toList()));
				assetCardService.updateStatus(assetCardIds, CardStatusEnum.USING.getCode());
			}
			return super.saveOrUpdateBatch(borrows);
		}
		return Boolean.FALSE;
	}

	@Override
	public List<BorrowExcelDTO> listBorrow(QueryWrapper<Borrow> query) {
		List<Borrow> borrows = this.baseMapper.selectListByScope(query, new DataScope());
		if (CollUtil.isNotEmpty(borrows)) {
			return borrows.stream().map(borrow -> {
				BorrowExcelDTO excelDTO = new BorrowExcelDTO();
				BeanUtil.copyProperties(borrow, excelDTO);
				return excelDTO;
			}).collect(Collectors.toList());
		}
		return Lists.newArrayList();
	}

	@Override
	public IPage<Borrow> page(Page page, QueryWrapper queryWrapper, BorrowSearchDTO borrow) {
		queryWrapper.eq("del_flag", 0);
		return this.baseMapper.page(page, queryWrapper, borrow,new DataScope());
	}

	@Override
	public R batchDelete(List<Long> ids) {
		List<Borrow> borrowList = this.list(Wrappers.<Borrow>query().lambda().in(BaseEntity::getId, ids));
		if (CollUtil.isEmpty(borrowList)) {
			return R.failed("未找到相应的（借用&归还）数据");
		}
		CloudUser user = SecurityUtils.getUser();
		boolean allMatch = borrowList.stream().allMatch(borrow -> AssetStatusEnum.DRAFT.getCode().equals(borrow.getStatus()) && user.getId().equals(borrow.getCreateId()));
		if (!allMatch) {
			return R.failed("只能删除草稿状态且创建用户为当前用户的（借用&归还）数据");
		}
		boolean remove = this.borrowListService.remove(Wrappers.<BorrowList>query().lambda().in(BorrowList::getParentId, ids));
		boolean delete = this.removeBatchByIds(ids);
		if (!delete && !remove) {
			return R.failed("删除失败，请检查数据有效性");
		}
		return R.ok(CommonConstants.SUCCESS, "删除成功");
	}


	@Override
	public boolean approval(Borrow borrow) {
		boolean save = this.updateById(borrow);
		List<BorrowList> borrowListList = this.borrowListService.list(Wrappers.<BorrowList>query().lambda().eq(BorrowList::getParentId, borrow.getId()));
		if(save){
			List<Long> ids = borrowListList.stream().map(BorrowList::getAssetCardId).distinct().collect(Collectors.toList());
			List<AssetCard> assetCardList = assetCardService.listByIds(ids);
			List<AssetCard> saveAssetCardList = Lists.newArrayList();
			ids.forEach(assetCardId -> {
				Optional<AssetCard> aessetCardOptional = assetCardList.stream().filter(assetCard -> assetCard.getId().equals(assetCardId)).findFirst();
				if(aessetCardOptional.isPresent()){
					AssetCard assetCard = aessetCardOptional.get();
					assetCard.setStatus(CardStatusEnum.BORROW.getCode());
					// TODO: 借用是否需要修改使用人
					saveAssetCardList.add(assetCard);
				}
			});
			// 修改资产使用信息
			return this.assetCardService.saveOrUpdateBatch(saveAssetCardList);
		}
		return save;
	}

	private BorrowCreateDTO.DictOption getDictOption() {
		BorrowCreateDTO.DictOption dictOption = new BorrowCreateDTO.DictOption();
		dictOption.setUserTreeList(userService.tree().getData());
		return dictOption;
	}

	private void saveOrUpdateBefore(Borrow entity) {
		List<BorrowList> borrowList = entity.getBorrowList();
		if (CollUtil.isNotEmpty(borrowList)) {
			StringBuilder detailed = new StringBuilder();
			borrowList.forEach(p -> detailed.append(p.getName()).append(","));
			detailed.deleteCharAt(detailed.length() - 1);
			entity.setDetailed(detailed.toString());
		}
		if (ObjectUtil.isNotEmpty(entity.getBorrowId()) && entity.getBorrowId() > 0) {
			UserVO data = userService.getUserName(entity.getBorrowId()).getData();
			entity.setBorrowOuid(data.getDeptId());
			entity.setBorrowOuname(data.getDeptName());
			entity.setBorrowOufullname(Optional.ofNullable(data.getDeptFullName()).orElse(data.getDeptName()));
		}
	}

}
